"""
历史管理组件
"""

import tkinter as tk
import numpy as np
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from ..main_window import MainWindow


class HistoryManagerMixin:
    """历史管理 Mixin 类"""
    
    def _save_history_state(self: 'MainWindow'):
        """保存当前状态到历史栈（用于分割操作）"""
        try:
            # 创建状态快照
            state = {
                'type': 'segment',  # 操作类型
                'selected_points': [p.copy() for p in self.selected_points],
                'selected_labels': self.selected_labels.copy(),
                'selected_box': self.selected_box.copy() if self.selected_box is not None else None,
                'current_result': self.current_result,
                'current_result_image': self.current_result_image.copy() if self.current_result_image is not None else None,
                'image': None  # 分割操作不保存原图
            }
            
            # 如果当前不在历史栈的末尾，删除后续的历史记录
            if self.history_index < len(self.history_stack) - 1:
                self.history_stack = self.history_stack[:self.history_index + 1]
            
            # 添加新状态
            self.history_stack.append(state)
            self.history_index = len(self.history_stack) - 1
            
            # 限制历史记录数量
            if len(self.history_stack) > self.max_history:
                self.history_stack.pop(0)
                self.history_index -= 1
            
            # 更新按钮状态
            self._update_history_buttons()
            
            self.logger.debug(f"保存分割历史状态 (索引:{self.history_index}, 总数:{len(self.history_stack)})")
            
        except Exception as e:
            self.logger.error(f"保存历史状态失败: {e}", exc_info=True)
    
    def _save_image_replacement_history(self: 'MainWindow', new_image: np.ndarray, channel_config: dict):
        """保存图像替换历史（包含SAM输入图，用于撤销恢复）"""
        try:
            # 创建状态快照（保存替换前的状态）
            state = {
                'type': 'image_replacement',  # 操作类型
                'image': self.image.copy(),  # 保存SAM输入图（替换前）
                'new_image': new_image.copy(),  # 保存新图（替换后）
                'original_image': self.original_image.copy() if self.original_image is not None else None,  # 保存真正的原图
                'channel_config': channel_config,
                'selected_points': [p.copy() for p in self.selected_points],
                'selected_labels': self.selected_labels.copy(),
                'selected_box': self.selected_box.copy() if self.selected_box is not None else None,
                'current_result': self.current_result,
                'current_result_image': self.current_result_image.copy() if self.current_result_image is not None else None
            }
            
            # 如果当前不在历史栈的末尾，删除后续的历史记录
            if self.history_index < len(self.history_stack) - 1:
                self.history_stack = self.history_stack[:self.history_index + 1]
            
            # 添加新状态
            self.history_stack.append(state)
            self.history_index = len(self.history_stack) - 1
            
            # 限制历史记录数量
            if len(self.history_stack) > self.max_history:
                self.history_stack.pop(0)
                self.history_index -= 1
            
            # 更新按钮状态
            self._update_history_buttons()
            
            self.logger.debug(f"保存图像替换历史 (索引:{self.history_index}, 总数:{len(self.history_stack)})")
            
        except Exception as e:
            self.logger.error(f"保存图像替换历史失败: {e}", exc_info=True)
    
    def _restore_history_state(self: 'MainWindow', index: int):
        """恢复指定索引的历史状态"""
        try:
            if index < 0 or index >= len(self.history_stack):
                self.logger.warning(f"无效的历史索引: {index}")
                return False
            
            state = self.history_stack[index]
            state_type = state.get('type', 'segment')
            
            # 根据状态类型进行不同的恢复
            if state_type == 'image_replacement':
                # 图像替换操作的恢复
                return self._restore_image_replacement_state(index, state)
            else:
                # 分割操作的恢复
                return self._restore_segment_state(index, state)
            
        except Exception as e:
            self.logger.error(f"恢复历史状态失败: {e}", exc_info=True)
            return False
    
    def _restore_segment_state(self: 'MainWindow', index: int, state: dict):
        """恢复分割操作状态"""
        # 恢复选择状态
        self.selected_points = [p.copy() for p in state['selected_points']]
        self.selected_labels = state['selected_labels'].copy()
        self.selected_box = state['selected_box'].copy() if state['selected_box'] is not None else None
        
        # 恢复分割结果
        self.current_result = state['current_result']
        self.current_result_image = state['current_result_image'].copy() if state['current_result_image'] is not None else None
        
        # 重绘画布
        self._redraw_selection_markers()
        
        # 显示结果
        if self.current_result_image is not None:
            self.display_image(self.current_result_image, self.result_canvas)
            
            smooth_status = " (已平滑)" if self.smooth_mask_var.get() else ""
            if self.current_result:
                self.update_status(f"已恢复到历史状态 (得分: {self.current_result.score:.3f}){smooth_status}")
            else:
                self.update_status("已恢复到历史状态")
        else:
            # 清空结果画布
            self.result_canvas.delete("all")
            self.update_status("已恢复到历史状态")
        
        # 更新历史索引
        self.history_index = index
        
        # 更新按钮状态
        self._update_history_buttons()
        
        self.logger.info(f"恢复分割历史状态 (索引:{index})")
        return True
    
    def _restore_image_replacement_state(self: 'MainWindow', index: int, state: dict):
        """恢复图像替换状态"""
        # 确定要恢复的SAM输入图像
        # 如果是撤销（向前），恢复到替换前的图像
        # 如果是重做（向后），恢复到替换后的图像
        if index < self.history_index:
            # 撤销：恢复SAM输入为原始状态
            restored_image = state['image'].copy()
            operation_desc = "撤销通道替换，恢复SAM输入为原图"
        else:
            # 重做：恢复SAM输入为通道图
            restored_image = state['new_image'].copy()
            
            # 显示通道配置信息
            channel_config = state['channel_config']
            enabled = []
            weights = channel_config['weights']
            if channel_config['enabled_channels']['r']:
                enabled.append(f"R({weights['r']:.1f})")
            if channel_config['enabled_channels']['g']:
                enabled.append(f"G({weights['g']:.1f})")
            if channel_config['enabled_channels']['b']:
                enabled.append(f"B({weights['b']:.1f})")
            
            channel_info = ', '.join(enabled)
            operation_desc = f"重做通道替换 (通道: {channel_info})"
        
        # 替换SAM输入图像
        self.image = restored_image
        
        # 恢复真正的原图（用于裁剪）
        if 'original_image' in state and state['original_image'] is not None:
            self.original_image = state['original_image'].copy()
        
        # 恢复其他状态
        self.selected_points = [p.copy() for p in state['selected_points']]
        self.selected_labels = state['selected_labels'].copy()
        self.selected_box = state['selected_box'].copy() if state['selected_box'] is not None else None
        self.current_result = state['current_result']
        self.current_result_image = state['current_result_image'].copy() if state['current_result_image'] is not None else None
        
        # 重新显示图片（显示SAM输入图）
        self.display_original_image()
        
        # 重绘选择标记
        self._redraw_selection_markers()
        
        # 显示结果
        if self.current_result_image is not None:
            self.display_image(self.current_result_image, self.result_canvas)
        else:
            self.result_canvas.delete("all")
        
        # 更新历史索引
        self.history_index = index
        
        # 更新按钮状态
        self._update_history_buttons()
        
        self.update_status(f"✓ {operation_desc}")
        self.logger.info(f"恢复图像替换状态 (索引:{index}, 操作:{operation_desc})")
        return True
    
    def _redraw_selection_markers(self: 'MainWindow'):
        """重绘选择标记（点和框）"""
        # 清除现有标记
        self.original_canvas.delete("selection")
        self.original_canvas.delete("tempbox")
        
        # 重绘点
        for i, (point, label) in enumerate(zip(self.selected_points, self.selected_labels)):
            img_x, img_y = point
            # 转换为画布坐标
            canvas_x = img_x * self.original_scale + self.original_offset_x
            canvas_y = img_y * self.original_scale + self.original_offset_y
            
            # 确定颜色
            if self.use_depth_input:
                color = "cyan"
            else:
                if label == 1:
                    color = self.config.get('ui.markers.foreground', 'green')
                else:
                    color = self.config.get('ui.markers.background', 'red')
            
            radius = self.config.get('ui.markers.marker_radius', 5)
            width = self.config.get('ui.markers.marker_width', 2)
            
            self.original_canvas.create_oval(
                canvas_x-radius, canvas_y-radius,
                canvas_x+radius, canvas_y+radius,
                fill=color, outline="white", width=width, tags="selection"
            )
        
        # 重绘框
        if self.selected_box is not None:
            x1, y1, x2, y2 = self.selected_box
            # 转换为画布坐标
            canvas_x1 = x1 * self.original_scale + self.original_offset_x
            canvas_y1 = y1 * self.original_scale + self.original_offset_y
            canvas_x2 = x2 * self.original_scale + self.original_offset_x
            canvas_y2 = y2 * self.original_scale + self.original_offset_y
            
            # 景深模式使用青色，普通模式使用配置的颜色
            if self.use_depth_input:
                color = "cyan"
            else:
                color = self.config.get('ui.markers.box', 'green')
            
            self.original_canvas.create_rectangle(
                canvas_x1, canvas_y1, canvas_x2, canvas_y2,
                outline=color, width=3, tags="selection"
            )
    
    def _update_history_buttons(self: 'MainWindow'):
        """更新撤销/重做按钮状态"""
        # 撤销按钮
        if self.history_index > 0:
            self.undo_btn.config(state=tk.NORMAL)
        else:
            self.undo_btn.config(state=tk.DISABLED)
        
        # 重做按钮
        if self.history_index < len(self.history_stack) - 1:
            self.redo_btn.config(state=tk.NORMAL)
        else:
            self.redo_btn.config(state=tk.DISABLED)
    
    def undo(self: 'MainWindow'):
        """撤销到上一个状态"""
        if self.history_index <= 0:
            self.update_status("没有可撤销的操作")
            return
        
        # 恢复到上一个状态
        self._restore_history_state(self.history_index - 1)
        
        self.logger.info(f"执行撤销 (当前索引:{self.history_index})")
    
    def redo(self: 'MainWindow'):
        """重做到下一个状态"""
        if self.history_index >= len(self.history_stack) - 1:
            self.update_status("没有可重做的操作")
            return
        
        # 恢复到下一个状态
        self._restore_history_state(self.history_index + 1)
        
        self.logger.info(f"执行重做 (当前索引:{self.history_index})")

